# frozen_string_literal: true

class Schema < ApplicationRecord
  include UuidGenerator

  module Status
    extend ConstantEnum

    CREATED = 'created'
    DEPLOYED = 'deployed'
  end

  has_many :schema_variables, dependent: :destroy
  has_many :input_variables,
           -> { where(io_type: SchemaVariable::IoType::INPUT).ordinal_asc },
           class_name: 'SchemaVariable'
  has_many :output_variables,
           -> { where(io_type: SchemaVariable::IoType::OUTPUT).ordinal_asc },
           class_name: 'SchemaVariable'

  has_many :rule_schemas
  has_many :rule_entities, through: :rule_schemas

  before_create :init_status

  scope :filter_name, ->(name) { where '`name` like ?', "%#{name}%" if name.present? }
  scope :filter_status, ->(status) { where status: status if status.present? }

  validates :name, presence: true
  validates :status,
            presence: false,
            inclusion: { in: %w[created validated deployed] },
            allow_blank: true

  # params = {
  #   input: {
  #     shipper: "Flexport Demo Shipper",
  #     consignee: "Flexport Demo Consignee"
  #   },
  #   output: {
  #     ofo_id: 1,
  #     ofo_name: "kira zhou"
  #   }
  # }
  def validate_variables?(params)
    validate_inputs?(params[:input]) && validate_outputs?(params[:output])
  end

  # params = {
  #   shipper: "Flexport Demo Shipper",
  #   consignee: "Flexport Demo Consignee"
  # }
  def validate_inputs?(params)
    input_variables.all? do |variable|
      variable.validate?(params)
    end
  end

  # params = {
  #   ofo_id: 1,
  #   ofo_name: "kira zhou"
  # }
  def validate_outputs?(params)
    output_variables.all? do |variable|
      variable.validate?(params)
    end
  end

  def format_outputs(params)
    output_variables.each do |variable|
      name = variable.name
      params[name] = variable.variable_type.parse(params[name]) if params.key?(name) && params
    end
    params
  end

  def input_types_map
    input_variables.map { |variable| [variable.name, variable.variable_type] }.to_h
  end

  def output_types_map
    output_variables.map { |variable| [variable.name, variable.variable_type] }.to_h
  end

  def deploy
    return if deployed?

    raise 'Validate schema error.' unless validate?

    update! status: Status::DEPLOYED
  end

  def validate
    raise 'Validate schema error.' unless validate?

    update! status: Status::VALIDATED if created?
  end

  def validate?
    return true unless created?

    true
  end

  def created?
    status.eql? Status::CREATED
  end

  def deployed?
    status.eql? Status::DEPLOYED
  end

  private

  def init_status
    self.status = Status::CREATED
  end
end
